#include "Function.hpp"
#include "EquationSolver.hpp"
#include <iostream>
#include <cmath>

const double Pi = acos(-1.);

class F1 : public Function {
public:
    double operator() (double x) const {
        return sin(x/2) - 1;
    }
};

class F2 : public Function {
public:
    double operator() (double x) const {
        return exp(x) - tan(x);
    }
};

class F3 : public Function {
public:
    double operator() (double x) const {
        return pow(x,3) - 12*pow(x,2) + 3*x + 1;
    }
};

void solve_f1() {
    // x_0 = 0, x_1 = pi/2
    std::cout << "Solving sin(x/2) -1 with x_0 = 0, x_1 = pi/2" << std::endl;
    Secant_Method solver_f11(F1(), 0, Pi/2);
    double x1 = solver_f11.solve();
    std::cout << "A root is: " << x1 << std::endl;

    // x_0 = 6, x_1 = 2pi
    std::cout << "Solving sin(x/2) -1 with x_0 = 6, x_1 = 2pi" << std::endl;
    Secant_Method solver_f12(F1(), 6, 2*Pi);
    double x2 = solver_f12.solve();
    std::cout << "A root is: " << x2 << std::endl;
}

void solve_f2() {
    // x_0 = 1, x_1 = 1.4
    std::cout << "Solving e^x - tanx with x_0 = 1, x_1 = 1.4" << std::endl;
    Secant_Method solver_f21(F2(), 1, 1.4);
    double x1 = solver_f21.solve();
    std::cout << "A root is: " << x1 << std::endl;

    // x_0 = 0, x_1 = 0.5
    std::cout << "Solving e^x - tanx with x_0 = 1.2, x_1 = 1.5" << std::endl;
    Secant_Method solver_f22(F2(), 1.2, 1.5);
    double x2 = solver_f22.solve();
    std::cout << "A root is: " << x2 << std::endl;
}

void solve_f3() {
    std::cout << "Solving x^3 - 12x^2 + 3x + 1 with x_0 = 0, x_1 = -0.5" << std::endl;
    Secant_Method solver_f31(F3(), 0, -0.5);
    double x1 = solver_f31.solve();
    std::cout << "A root is: " << x1 << std::endl;

    std::cout << "Solving x^3 - 12x^2 + 3x + 1 with x_0 = -1, x_1 = 0" << std::endl;
    Secant_Method solver_f32(F3(), -1, 0);
    double x2 = solver_f32.solve();
    std::cout << "A root is: " << x2 << std::endl;
}
/* Type your code here */

int main() {
    solve_f1();
    solve_f2();
    solve_f3();
    /* Type your code here */
    return 0;
}